package appli;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

import javax.vecmath.Vector2d;

import sma.agents.ObstacleAgent;
import sma.agents.channels.ObstacleChannel;
import sma.agents.channels.DirectionChannel;
import sma.agents.listeners.DirectionListener;

import appli.utils.Config;

/**
 * 
 * This class is called each time the vehicule move and send his new position 
 * to the telemeter using Janus channel
 * 
 * @author Etienne Sainton
 * @author Arnaud Schaeffer  
 * 
 * @version 0.2
 * @since 0.1
 */
public class Direction implements Runnable, DirectionListener {

	private InetAddress host;

	private Integer port;

	private SocketChannel socketChannel;
	
	private Socket socket;


	private Integer size;
	
	private ServerSocket sServer;
	
	private InetSocketAddress hoteAdress ;
	
	/**
	 * Creates a thread
	 * 
	 * @param host
	 *            - the host name, or null for the loopback address.
	 * @param port
	 *            - the port number
	 * @param s 
	 * 			  - buffer (always 0 in our case)
	 */
	public Direction(String host, Integer port, Integer s) {
		boolean test = false;
		
		if(Config.SIMULATE){
			do {
				try {
					this.host = InetAddress.getByName(host);
					this.port = new Integer(port);
					this.size = s;
					
					this.sServer = new ServerSocket(this.port);
		
					//initSocket();
					test = true;
				} catch (IOException e) {
					e.printStackTrace();
				}
			} while(test == false);
		}else{
			do {
				try {
					this.host = InetAddress.getByName(host);
					this.port = new Integer(port);
					this.size = s;
					
					hoteAdress = new InetSocketAddress(host,port);
					this.socketChannel = SocketChannel.open();
					
					this.socketChannel.connect(hoteAdress);
					System.out.println("COucou");
					test = true;
				} catch (IOException e) {
					System.out.println("Erreur : " + e.getMessage());
					e.printStackTrace();
				}
			} while(test == false);
			
		}
	
	}
	
	/**
	 * Initiate the socket
	 */
	public void initSocket(){
		if(Config.SIMULATE){
			try {
				socket = sServer.accept();
				System.out.println("socket : "+socket);
			} catch (IOException e) {
				System.out.println("Pas de socket...");
				e.printStackTrace();
			}	
		}
		
	}
	
	
	/**
	 * @return the port
	 */
	public Integer getPort() {
		return port;
	}

	@Override
	public void onMoveVehicule(Vector2d move) {
		sendDeplacement(move);
	}

	/**
	 * Send the movement to the vehicle
	 * @param move movement vector2d
	 */
	private void sendDeplacement(Vector2d move) {	
		if(socket != null  || !Config.SIMULATE){
			try {
				if(Config.SIMULATE){
					DataOutputStream writer = new DataOutputStream(socket.getOutputStream());
					writer.writeInt((int)move.x - Config.PANEL_SIZE);
					writer.writeInt((int)move.y - Config.PANEL_SIZE - 60);
				}else{
					
					sendChar('R');
					sendFloat(0.99f);	//la vitesse
					sendFloat(0.99f);	//la direction
					sendFloat(0f);		//arret d'urgence
					
				}
				
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println("Position vehicule : " + e.getMessage());
			}
		}else{
			//System.out.println("Send Commande : Socket null");
		}
	}

	private void sendFloat(float f) throws IOException {
		ByteBuffer byteBuf = ByteBuffer.allocate(4);
		byteBuf.order(ByteOrder.LITTLE_ENDIAN);
		
		byteBuf.putFloat(f);
		
		byteBuf.flip();

		while(byteBuf.hasRemaining()) {
			socketChannel.write(byteBuf);
		}
		
	}
	

	private void sendChar(char c) throws IOException {
		byte bValue = (byte)c;
		ByteBuffer byteBuf = ByteBuffer.allocate(1);
		byteBuf.order(ByteOrder.LITTLE_ENDIAN);
		byteBuf.put(bValue);
		
		byteBuf.flip();

		while(byteBuf.hasRemaining()) {
			socketChannel.write(byteBuf);
		}
	}

	@Override
	public void run() {
		initSocket();
		
	}

}
